package net.gdface.cassdk;

import android.support.test.runner.AndroidJUnit4;

import static org.junit.Assert.*;

import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.gdface.sdk.CodeInfo;
import net.gdface.sdk.FaceApiGenericDecorator;
import net.gdface.sdk.fse.BaseFeatureSearchEngine;
import net.gdface.sdk.fse.CodeBean;
import net.gdface.sdk.fse.FeatureSeDecorator;
import net.gdface.sdk.fse.JNIException;
import net.gdface.utils.BufferUtils;
import net.gdface.utils.FaceUtilits;
import net.gdface.utils.SampleLog;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@RunWith(AndroidJUnit4.class)
public class FseTest {
	private static final Logger logger = LoggerFactory.getLogger(FaceApiTest.class);
	private static FaceApiGenericDecorator faceapi;

	private static CodeInfo[] codes;
	private static CodeInfo[] codes054;
	private static FeatureSeDecorator fse;
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		// fse必须要在faceapi之前初始化，否则在searchCode方法执行feature compare时会抛出异常，
		// 直接原因是算法未初始化，但根本原因还不清楚
		fse = FeatureSeDecorator.makeDecorator(FseAndroidBridge.getFeatureSe());
		faceapi= new FaceApiGenericDecorator(FaceApiCasAndroid.getInstance());
		codes = faceapi.detectAndGetCodeInfo(FaceApiTest.class.getResourceAsStream("/images/he049.jpg"), 0);
		codes054 = faceapi.detectAndGetCodeInfo(FaceApiTest.class.getResourceAsStream("/images/he054.jpg"), 0);
		logger.info("find face {} in he168.jpg", codes054.length);
	}

	@Test
	public void test2Exception() {
		try {
			fse.getFeature((byte[])null);
			assertFalse(true);
		} catch(JNIException e){
			SampleLog.log("{}:{}",e.getClass().getSimpleName(),e.getMessage());
		} catch(IllegalArgumentException e){
			SampleLog.log("{}:{}",e.getClass().getSimpleName(),e.getMessage());			
		}catch (Throwable e) {
			e.printStackTrace();
			assertFalse(true);
		}
	}
	@Test 
	public void test3TestAddFeature(){
		int count =0;
		for(CodeInfo c:codes){
			logger.info("{}:add feature {}\tFRECT={}",++count,FaceUtilits.getMD5String(c.getCode()),c.getPos());
			//fse.addFeature(FaceUtilits.getMD5(c.getCode()), c.getCode());
			fse.addFeature((byte[])null, c.getCode(), null);
			CodeBean b = fse.getFeature(FaceUtilits.getMD5(c.getCode()));
			assertTrue(null!=b);
		}		
		logger.info("========================");
		for(CodeInfo c: codes054){
			logger.info("{}:add feature {}\tFRECT={}",++count,FaceUtilits.getMD5String(c.getCode()),c.getPos());
			//fse.addFeature(FaceUtilits.getMD5(c.getCode()), c.getCode());
			fse.addFeature((byte[])null, c.getCode(), null);
			CodeBean b = fse.getFeature(FaceUtilits.getMD5(c.getCode()));
			assertTrue(null!=b);
		}
	}
	@Test
	public void test4GetFeature() {
		try {
			CodeBean result = fse.getFeature("11111111111111111111111111111111");
			assertTrue(null == result);
		} catch(JNIException e){
			SampleLog.log("{}:{}",e.getClass().getSimpleName(),e.getMessage());
			assertFalse(true);
		} catch (Throwable e) {
			e.printStackTrace();
			assertFalse(true);
		}
	}
	@Test
	public void test5TestSearchFeature(){
		CodeInfo feature = codes[0];
		CodeBean[] result = fse.searchCode(feature.getCode(), 0.5, 10);
		logger.info("search result:");
		int rank=0;
		for(CodeBean cb:result){
			logger.info("No:{}:id={}\tsimilarity={}",++rank,FaceUtilits.toHex(cb.id),cb.similarity);
		}
	}
	@Test
	public void test6() {
		try {
			SampleLog.log("size = {}",FseAndroidBridge.size());
			SampleLog.log("statistic info:\n{}", FseAndroidBridge.statInfo());
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
	@Test
	public void test7TestRemove(){
		for(CodeInfo c:codes){
			fse.removeFeature(FaceUtilits.getMD5(c.getCode()));
			logger.info("remove feature {}\tsize={}",FaceUtilits.getMD5String(c.getCode()),fse.size());
		}
	}
/*	@Test
	public void  test8TestCompare(){
		double[] dbuffer = BufferUtils.asDoubleArray(codes[0].getCode());
		logger.info("dbuffer={}",dbuffer);
		double sim = BaseFeatureSearchEngine.compare(codes[0].getCode(),codes[0].getCode());
		logger.info("sim={}",sim);
	}*/
}
